all files / src/validators/ game.validators.ts

37.5% Statements 15/40
0% Branches 0/18
25% Functions 2/8
44.12% Lines 15/34
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61                                                                                            
import { Game, Player, Phase } from '../game.interfaces';
import { Bid, Action, BID, REGISTER_PLAYER, SHARE_STOCK, ShareStock, RegisterPlayer, THROW_CARD, throwCard, ThrowCard, DECLARE_BOMB, DeclareBomb } from '../game.actions';
import { canBid } from './bid.validator';
import { canShareStock } from './stock.validator';
import { canRegisterPlayer } from './player.validator';
import { getWinner, getTotalBombsByPlayer, getPlayerTotalPoints, getPlayerById, isOnBarrel } from '../helpers/players.helpers';
import { canThrowCard } from './battle.validator';
import * as _ from 'lodash';
import { isTableEmpty, getTotalWonCards } from '../helpers/battle.helpers';
import { getBidWinner } from '../helpers/bid.helpers';
 
export function can(state: Game, action: Action): boolean {
    return {
        [REGISTER_PLAYER]: (s, a) => canRegisterPlayer(s, a as RegisterPlayer),
        [BID]:             (s, a) => canBid(s, a as Bid),
        [SHARE_STOCK]:     (s, a) => canShareStock(state, action as ShareStock),
        [THROW_CARD]:      (s, a) => canThrowCard(state, action as ThrowCard),
        [DECLARE_BOMB]:    (s, a) => canDeclareBomb(state, action as DeclareBomb),
    }[action.type](state, action);
}
 
export function isGameFinished(state: Game): boolean {
    const winner: Player = getWinner(state.players);
    return !!winner;
}
 
export function canDeclareBomb(state: Game, { player }: DeclareBomb): boolean {
    const { battle } = state;
 
    const inAllowedPhase = _.includes([
        Phase.SHARE_STOCK,
        Phase.BATTLE_START,
        Phase.TRICK_START,
        Phase.TRICK_IN_PROGRESS
    ], state.phase);
 
    if(!inAllowedPhase) { return false; }
 
    const bidWinner = getBidWinner(state.bid).player;
 
    //only player who won bidding is allowed
    if(bidWinner !== player) { return false; }
 
    //number of declared bomd must not exceed configuration value
    
    if (getTotalBombsByPlayer(state, player) >= state.settings.maxBombs) { return false; }
 
    //when in barrel, prevent throwing bomb
    if (state.settings.permitBombOnBarrel && isOnBarrel(state, getPlayerById(state.players, player))) {
        return false;
    }
    
    //when trick in progress
    if(state.phase === Phase.TRICK_IN_PROGRESS) {
        if (state.battle.leadPlayer !== player)  { return false; } //player should be trick leader
        if (!isTableEmpty(battle)) { return false; } //some cards throw on the table
        if (getTotalWonCards(state) > 0) { return false; } //some tricks already finished
    }
 
    return true;
}